import time #导入 time 模块，用于计算程序运行时间。
import os #导入 os 模块，用于处理文件和目录。
import cv2 #导入 cv2 模块，用于处理图像。
import numpy as np #导入 numpy 模块，用于处理数组。
from imutils import paths  # 导入imutils中的paths工具,用于获取文件路径
import pickle #导入 pickle 模块，用于读取和保存数据。
from sklearn.model_selection import train_test_split #导入 train_test_split 函数，用于将数据集分割为训练集和测试集。
from lazypredict.Supervised import LazyClassifier #导入 LacyClassifier 类，用于训练和评估分类器。
from tabulate import tabulate #导入 tabulate 函数，用于将数据以表格的形式打印出来。
from tqdm import tqdm #导入 tqdm 函数，用于在循环中显示进度条。
import logging #导入 logging 模块，用于记录日志。
from sklearn.preprocessing import StandardScaler #导入 StandardScaler 类，用于数据标准化。

# 配置 logging，确保能够打印正在运行的函数名
logging.basicConfig(level=logging.INFO,format='%(asctime)s-%(levelname)s-%(message)s')

def getsize(file):  #转换后的  MB
    return  os.path.getsize(file)/(1024*1024)

def createXY(train_floder,dest_floder,method='flat',batch_size=64):
    
    image_paths=list(paths.list_images(train_floder)) #获取训练文件夹中所有图像的路径

    if not image_paths:
        logging.error(f"没有在 {train_floder} 中找到图像")
        return [], []
    
    X=[] #初始化 X 列表，用于存储特征
    y=[] #初始化 y 列表，用于存储标签   

    #计算需要的批次数 
    num_batchs=len(image_paths)//batch_size+(1 if len(image_paths)%batch_size else 0)  
    for idx in range(num_batchs):
        batch_images=[] #初始化存储批次图像的列表
        batch_labels=[] #初始化存储批次标签的列表

        start=idx*batch_size #计算批次开始的索引
        end=min((idx+1)*batch_size,len(image_paths)) #计算批次结束的索引

        for i in range(start,end): #对于每个批次中的图像  
            image_path=image_paths[i]  #获取图像的路径
            img=cv2.imread(image_path,0) #以灰度模式读取图像
            if img is None:
                logging.error(f"无法读取图像: {image_path}")
                continue
            img=cv2.resize(img,(32,32))    #将图像调整为32x32
            batch_images.append(img)  #将图像数组添加到批次图像列表

            label = image_path.split(os.path.sep)[-1].split(".")[0]  # 从文件名中解析标签
            label = 1 if label == 'dog' else 0  # 如果标签是'dog'则为1,否则为0
            batch_labels.extend([label])

        batch_images = np.array(batch_images)  # 将批次图像列表转换为numpy数组
        batch_pixels=batch_images.reshape((batch_images.shape[0], -1))  # 将图像展平
    
        X.extend(batch_pixels)  # 将处理后的图像特征添加到X列表
        y.extend(batch_labels)  # 将标签添加到y列表
        
    return X,y    #打印 y 文件的大小
if __name__ == "__main__":

    X, y = createXY(train_floder="./train", dest_floder=".", method='flat')
    X = np.array(X).astype('float32') #将 X 转换为 float32 类型
    y=np.array(y) #将 y 转换为数组类型



    # 使用stratify参数进行数据分割
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=123)
    
    
    scaler = StandardScaler() #创建标准化对象
    X_train_scaled = scaler.fit_transform(X_train) #对训练集进行标准化
    X_test_scaled = scaler.transform(X_test) #对测试集进行标准化

    clf=LazyClassifier()    #创建分类器
    result,_=clf.fit(X_train,X_test,y_train,y_test) #训练分类器
    print(result)

    best_model_name=result['Accuracy'].idxmax()   #获取最佳分类器的名称
    print("\n accuracy最高的分类器是： ",best_model_name)

    best_model=clf.models[best_model_name]    #获取最佳分类器
    result=best_model.predict(X_test)      #使用最佳分类器进行预测
    with open("best_model.pkl",'wb') as f:
        pickle.dump(best_model,f)   #将最佳分类器保存到 best_model.pkl 文件中

    print(f"用{best_model_name}分类器预测X_test的结果是：\n{result}")